package com.sencorsta.ids.core.tcp.socket.protocol;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sencorsta.ids.core.configure.GlobalConfigure;
import com.sencorsta.ids.core.configure.TypeProtocol;
import com.sencorsta.ids.core.configure.TypeSerialize;
import com.sencorsta.ids.core.entity.ErrorMsg;
import com.sencorsta.ids.core.log.Out;
import com.sencorsta.ids.core.tcp.opensocket.OpenMessage;
import com.sencorsta.ids.core.tcp.opensocket.OpenServerBootstrap;
import com.sencorsta.ids.core.tcp.socket.NetHandler;

import io.netty.channel.Channel;

public abstract class RpcMessageHandler extends NetHandler {

    public abstract RpcMessage request(Channel channel, JSONObject json, String content, byte[] data, byte[] protobuf);

    public long msgId;

    public RpcMessage response(JSONObject json) {
        JSONObject res = new JSONObject();
        res.put("code", 0);
        res.put("msg", "成功");
        res.put("data", json);
        return response(res.toJSONString().getBytes(GlobalConfigure.UTF_8), TypeSerialize.TYPE_JSON);
    }

    public RpcMessage success() {
        JSONObject res = new JSONObject();
        res.put("code", 0);
        res.put("msg", "成功");
        return response(res.toJSONString().getBytes(GlobalConfigure.UTF_8), TypeSerialize.TYPE_JSON);
    }

    public RpcMessage empty() {
        return null;
    }

    public RpcMessage error(ErrorMsg errorMsg) {
        JSONObject res = new JSONObject();
        res.put("code", errorMsg.code);
        res.put("msg", errorMsg.Msg);
        return response(res.toJSONString().getBytes(GlobalConfigure.UTF_8), TypeSerialize.TYPE_JSON);
    }


    public RpcMessage response(String content) {
        return response(content.getBytes(GlobalConfigure.UTF_8), TypeSerialize.TYPE_STRING);
    }

    public RpcMessage response(byte[] data, short typeSerialize) {
        RpcMessage response = new RpcMessage();
        response.header.type = TypeProtocol.TYPE_RPC_RES;
        response.channel = channel();
        response.method = method + ".C";
        response.serializeType = typeSerialize;
        response.data = data;
        return response;
    }

    protected String method;

    @Override
    public void execute(RpcMessage message) {
        msgId = message.msgId;
        short serializeType = message.serializeType;
        method = message.method;
        RpcMessage response = null;
        switch (serializeType) {
            case TypeSerialize.TYPE_JSON:
                JSONObject data = JSON.parseObject(new String(message.data, GlobalConfigure.UTF_8));
                Out.debug(Thread.currentThread().getName(),"执行方法:", " -> ", method, "参数:", data);
                response = request(message.channel, data, null, null, null);
                break;
            case TypeSerialize.TYPE_STRING:
                Out.debug(Thread.currentThread().getName(),"执行方法:", " -> ", method, "参数:", new String(message.data, GlobalConfigure.UTF_8));
                response = request(message.channel, null, new String(message.data, GlobalConfigure.UTF_8), null, null);
                break;
            case TypeSerialize.TYPE_BYTEARR:
                Out.debug(Thread.currentThread().getName(),"执行方法:", " -> ", method, "参数:", Arrays.toString(message.data));
                response = request(message.channel, null, null, message.data, null);
                break;
            case TypeSerialize.TYPE_PROTOBUF:
                Out.debug(Thread.currentThread().getName(),"执行方法:", " -> ", method, "参数:", Arrays.toString(message.data));
                response = request(message.channel, null, null, null, message.data);
                break;
            default:
                break;
        }

        if (msgId>=0&&response != null) {
            if (response.header.type == TypeProtocol.TYPE_RES) {
                Out.debug("执行完毕:", method, " -> ", "返回(open):", response);
                OpenMessage open = new OpenMessage();
                open.method = response.method;
                open.serializeType = response.serializeType;
                open.data = response.data;
                open.header.type = TypeProtocol.TYPE_RES;
                open.channel=response.channel;
                //response.channel.writeAndFlush(open);
                OpenServerBootstrap.getInstance().addMessage(open);
            } else {
                Out.debug("执行完毕:", method, " -> ", "返回(rpc):", response);
                response.msgId = msgId;
                write(response);
            }
        } else {
            Out.trace("执行完毕:", method, " -> ", "无返回");
        }
        Out.trace("");
    }


    public byte[] protpToByte(com.google.protobuf.GeneratedMessageV3.Builder res) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        try {
            res.build().writeTo(output);
        } catch (IOException e) {
            e.printStackTrace();
        }
        byte[] byteArray = output.toByteArray();
        return byteArray;
    }

}
